package org.apache.commons.graph.view

import com.gitee.wsl.func.consumer.Consumer
import org.apache.commons.graph.bean.Edge


interface IGraphViewBase<V, E : Edge<V>> : ITargetVertexView<V> {
    override fun vertexSet(): Collection<V>

    fun edgeSet(): Collection<E>
}


interface IDirectedGraphVertexView<V> : ISourceVertexView<V>, ITargetVertexView<V>


interface IDirectedGraphView<V, E : Edge<V>> : IForwardGraphView<V, E>, IBackwardGraphView<V, E>,
    IGraphViewBase<V, E> {
    fun cloneInstance(): IDirectedGraphView<V, E>

    /**
     * 反转图中边的方向，source->target, target->source
     *
     * @return
     */
    fun reverse(): IDirectedGraphView<V, E>

    override fun vertexSet(): Set<V>

    override fun edgeSet(): Set<E>

    val vertexCount: Int
        get() = vertexSet().size

    val edgeCount: Int
        get() = edgeSet().size

    override fun getOutwardEdges(source: V): List<E>

    override fun getInwardEdges(vertex: V): List<E>

    // void forEachTarget(V source, Consumer< super V> action);
    //
    // void forEachSource(V vertex, Consumer< super V> action);
    override fun getSourceVertexes(vertex: V): List<V>

    override fun getTargetVertexes(vertex: V): List<V>

    fun getEdge(source: V, target: V): E?

    fun containsEdge(source: V, target: V): Boolean {
        return getEdge(source, target) != null
    }

    override fun containsVertex(vertex: V): Boolean {
        return vertexSet().contains(vertex)
    }

    fun getInwardDegree(vertex: V): Int {
        val edges = getInwardEdges(vertex)
        return edges.size
    }

    fun getOutwardDegree(source: V): Int {
        val edges: Collection<E> = getOutwardEdges(source)
        return edges.size
    }

    override val isEmpty: Boolean
        get() = vertexSet().isEmpty()

    fun forEachVertex(action: Consumer<in V>) {
        vertexSet().forEach{action(it)}
    }

    fun forEachEdge(action: Consumer<in E>) {
        edgeSet().forEach{action(it)}
    }

    //
    // default Iterator<V> depthFirstIterator(V start) {
    // return new DepthFirstIterator<>(this, start);
    // }
    //
    // default Iterator<V> breadthFirstIterator(V start) {
    // return new BreadthFirstIterator<>(this, start);
    // }
    //
    // default Set<V> findCycles() {
    // return new CycleDetector<>(this).findCycles();
    // }
    // default TopologicalOrderIterator<V> topologicalOrderIterator(boolean allowLoop) {
    // return new TopologicalOrderIterator(vertexSet(), this, allowLoop);
    // }
    // default Set<V> reachableVertexes(V vertex) {
    // Set<V> set = new LinkedHashSet<>();
    // BreadthFirstIterator.reachable(set, this, vertex);
    // return set;
    // }
//    fun copyTo(graph: IDirectedGraph<V, E>) {
//        forEachVertex(Consumer { vertex: V ->
//            graph.addVertex(vertex)
//        })
//
//        forEachEdge(Consumer { edge: E ->
//            graph.addEdge(edge)
//        })
//    }
}